package com.bibimaya.auto.mapper.dao.utils;

import com.bibimaya.auto.mapper.dao.annotation.Column;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * EntityMap
 * Created by lijianwei
 */
public class EntityMap {

    private static final Map<Class, EntityMap> entityMaps = new HashMap<>();

    public static EntityMap newInstance(Class c, String classNameSuffix){
        if(entityMaps.containsKey(c)){
            return entityMaps.get(c);
        }
        synchronized (c){
            if(!entityMaps.containsKey(c)){
                EntityMap entityMap = new EntityMap(c, classNameSuffix);
                entityMaps.put(c, entityMap);
                return entityMap;
            }
        }
        return entityMaps.get(c);
    }

    private EntityMap(Class c){
        this.c = c;
        className = c.getCanonicalName();
        table = TableUtil.classToTableName(c.getSimpleName());
        covertFieldsToColumns(c);
    }

    private EntityMap(Class c, String classNameSuffix){
        this.c = c;
        className = c.getCanonicalName();
        this.classNameSuffix = classNameSuffix;
        table = TableUtil.classToTableName(c.getSimpleName(), classNameSuffix);
        covertFieldsToColumns(c);
    }

    /**
     * 字段转换为列名
     * @param c
     */
    private void covertFieldsToColumns(Class c){
        Class sc = c.getSuperclass();
        if(sc != null && !sc.isInterface()){
            covertFieldsToColumns(sc);
        }
        Field[] fieldsArray = c.getDeclaredFields();
        if(fieldsArray == null || fieldsArray.length == 0){
            return ;
        }
        for(int i = 0; i < fieldsArray.length; i++){
            Field field = fieldsArray[i];
            int modifier = field.getModifiers();
            if(Modifier.isFinal(modifier) || Modifier.isStatic(modifier)
                    || Modifier.isTransient(modifier) || Modifier.isVolatile(modifier)){
                continue;
            }
            FieldMap fm = new FieldMap();
            String fieldName= field.getName();
            fm.setField(fieldName);
            Column column = field.getAnnotation(Column.class);
            if(column != null){
                fm.setColumn(column.value());
                if(primaryKeyField == null && column.isPrimaryKey()){
                    fm.setPrimaryKey(true);
                    primaryKeyField = fm;
                }
            }else {
                fm.setColumn(TableUtil.fieldToColumnName(fieldName));
            }
            fm.setType(field.getType());
            fields.add(fm);
            columnMap.put(fm.getColumn(), fm);
        }
        if(primaryKeyField == null && !fields.isEmpty()){
            primaryKeyField = fields.get(0);
        }
    }

    /** class */
    private Class c;

    /** table */
    private String table;

    /** className */
    private String className;

    /** 类名的后缀 防止这个后缀解析成表名 */
    private String classNameSuffix;

    /** fields */
    private List<FieldMap> fields = new ArrayList<FieldMap>();

    private Map<String, FieldMap> columnMap = new HashMap<>();

    private FieldMap primaryKeyField;

    public String getTable() {
        return table;
    }

    public Class getC() {
        return c;
    }

    public void setC(Class c) {
        this.c = c;
    }

    public void setTable(String table) {
        this.table = table;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public List<FieldMap> getFields() {
        return fields;
    }

    public void setFields(List<FieldMap> fields) {
        this.fields = fields;
    }

    public FieldMap getPrimaryKeyField() {
        return primaryKeyField;
    }

    public void setPrimaryKeyField(FieldMap primaryKeyField) {
        this.primaryKeyField = primaryKeyField;
    }
}
